#ifndef _contest_vectord_h_
#define _contest_vectord_h_

#include<vector>
#include<stdint.h>
#include<assert.h>

using namespace std;

namespace contest
{

/*
 * A generic multidimensional array
 * @template T: type.
 * @template D: number of dimensions.
 */
template <typename T, size_t D> class vectord
{
};

/*
 * A 2D array
 */
template <typename T> class vectord<T, 2>
{
private:
    size_t rows, cols;
    vector<T> values;
public:
    vectord(const size_t r, const size_t c, const T v):
        values(r*c, v), rows(r), cols(c)
    {
    }
    T& operator()(const size_t i, const size_t j)
    {
        return values[i*cols + j];
    }
    const T& operator()(const size_t i, const size_t j) const
    {
        return values[i*cols + j];
    }
};

/*
 * A 3D array
 */
template <typename T> class vectord<T, 3>
{
private:
    size_t layers, rows, cols;
    vector<T> values;
public:
    vectord(const size_t x, const size_t y, const size_t z, const T v):
        values(x*y*z, v), layers(x), rows(y), cols(z)
    {
    }
    T& operator()(const size_t i, const size_t j, const size_t k)
    {
        return values[i*rows*cols + j*cols + k];
    }
    const T& operator()(const size_t i, const size_t j, const size_t k) const
    {
        return values[i*rows*cols + j*cols + k];
    }
};

void test_vectord()
{
    vectord<int, 2> mtx2(2, 2, 0);
    mtx2(0, 0) = 1;
    mtx2(0, 1) = 2;
    mtx2(1, 0) = 3;
    mtx2(1, 1) = 4;
    for (int i=0; i<2; ++i)
        for (int j=0; j<2; ++j)
            assert(mtx2(i, j) == i*2 + j + 1);

    vectord<int, 3> mtx3(2, 2, 2, 0);
    mtx3(0, 0, 0) = 1;
    mtx3(0, 0, 1) = 2;
    mtx3(0, 1, 0) = 3;
    mtx3(0, 1, 1) = 4;
    mtx3(1, 0, 0) = 5;
    mtx3(1, 0, 1) = 6;
    mtx3(1, 1, 0) = 7;
    mtx3(1, 1, 1) = 8;
    for (int i=0; i<2; ++i)
        for (int j=0; j<2; ++j)
            for (int k=0; k<2; ++k)
                assert(mtx3(i, j, k) == i*2*2 + j*2 + k + 1);
}

}

#endif
